using UnityEngine;

// 继承自MonoBehaviour，表示这是一个Unity组件脚本
public class Graph : MonoBehaviour { 

    [SerializeField] // 序列化字段，允许在Unity编辑器Inspector面板中显示和赋值
    Transform pointPrefab; // 点的预制体引用

    
    [SerializeField, Range(10, 100)] // 同时使用SerializeField和Range属性，在Inspector中显示为一个滑块
    int resolution = 10; // 定义生成点的数量（即图形的分辨率），默认10，范围在10到100之间

    // 用于存储所有生成出来的point的Transform引用
    Transform[] points; 

    // Awake方法在脚本实例被加载时调用，用于初始化
    void Awake () { 
        
        // 计算每个点之间的步长。总范围是2个单位（从-1到1），除以点数得到间隔
        float step = 2f / resolution; 
        
        // 声明并初始化一个临时变量，用于计算每个点的位置
        var position = Vector3.zero; 
        
        // 计算每个点的缩放尺寸，使用步长使其大小与间距相匹配，避免点重叠
        var scale = Vector3.one * step;
        
        // 初始化数组，长度为指定的分辨率
        points = new Transform[resolution];
        
        
        for (int i = 0; i < points.Length; i++) {
            
            // 实例化预制体，并将返回的Transform同时赋值给循环变量point和数组元素points[i]
            Transform point = points[i] = Instantiate(pointPrefab);
            
            // 计算当前点的x坐标：
            // (i + 0.5f) 将点放在每个区间的中心
            // * step 乘以步长得到实际位置
            // - 1f 将范围从[0, 2]偏移到[-1, 1]
            position.x = (i + 0.5f) * step - 1f; 
            
            // 设置实例化点的本地位置
            point.localPosition = position; 
            
            // 设置实例化点的本地缩放
            point.localScale = scale; 
            
            // 将新生成的点设置为当前游戏对象的子物体。
            // false表示保持世界坐标系的比例和旋转，而不是使用父物体的
            point.SetParent(transform, false);
        }
    }

    // Update方法每一帧都会被调用，用于更新动画
    void Update () {
        
        // 获取自游戏开始以来的时间（以秒为单位），每一帧都会增加
        float time = Time.time; 
        
        // 遍历所有点
        for (int i = 0; i < points.Length; i++) {
            
            // 获取当前索引对应的点的Transform
            Transform point = points[i];
            
            // 获取点的当前位置
            Vector3 position = point.localPosition;
            
            // 根据正弦函数计算新的y坐标：
            // Mathf.PI 使用π来延长正弦波周期
            // (position.x + time) 使波形随时间沿x轴负方向移动
            // Mathf.Sin 计算正弦值
            position.y = Mathf.Sin(Mathf.PI * (position.x + time));
            
            // 将计算出的新位置应用回点，更新其位置
            point.localPosition = position;
        }
    }
}